package com.raos.example.swagger.response;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.xml.bind.ValidationException;
import java.util.stream.Collectors;

/**
 * 全局异常处理
 *
 * @author raos
 * @email 991207823@qq.com
 * @date 2023/1/17 10:35
 */
@Slf4j
//@RestControllerAdvice(basePackages = {"com.raos.example"}) // 指定全局处理异常包拦截路径
@RestControllerAdvice
public class GlobalExceptionHandlerAdvice {

    /**
     * 默认全局异常处理。
     * @param e the e
     * @return ResultData
     */
    @ExceptionHandler(Exception.class) //指定处理异常类型
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) //@ResponseStatus指定客户端收到的http状态码
    public R<String> exception(Exception e) {
        log.error("全局异常信息 ex={}", e.getMessage(), e);
        return R.error(e.getMessage());
    }

    /**
     * Assert异常
     */
    @ExceptionHandler({IllegalArgumentException.class, IllegalStateException.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R<String> ArgumentException(Exception e) {
        log.error("Assert异常 ex={}", e.getMessage(), e);
        return R.error("参数检查异常：" + e.getMessage());
    }


    /**
     * 抓取自定义异常
     */
    @ExceptionHandler(RRException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R<String> exception(RRException e) {
        log.error("自定义异常 ex={}", e.getMessage(), e);
        return R.error(e.getCode(), e.getMessage());
    }

    /** 参数绑定校验异常 */
    @ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
    public ResponseEntity<R<String>> handleValidatedException(Exception e) {
        R<String> resp = R.error();

        if (e instanceof MethodArgumentNotValidException) {
            // BeanValidation exception
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            resp = R.error(HttpStatus.BAD_REQUEST.value(),
                    ex.getBindingResult().getAllErrors().stream()
                            .map(ObjectError::getDefaultMessage)
                            .collect(Collectors.joining("; "))
            );
        } else if (e instanceof BindException) {
            // BeanValidation GET object param
            BindException ex = (BindException) e;
            resp = R.error(HttpStatus.BAD_REQUEST.value(),
                    ex.getAllErrors().stream()
                            .map(ObjectError::getDefaultMessage)
                            .collect(Collectors.joining("; "))
            );
        }

        log.error("参数校验异常:{}", resp.getMsg());
        return new ResponseEntity<>(resp, HttpStatus.BAD_REQUEST);
    }

}
